import china from '@/assets/map/china.json'
import type { EChartsType } from 'echarts/core'
import type { GeoJSONCompressed } from 'echarts/types/src/coord/geo/geoTypes.js'
import { ECOption, echarts } from '@/utils/echarts'
import { useCallback, useEffect, useImperativeHandle, useRef } from 'react'
import { debounce } from 'lodash'

interface Props {
	option: ECOption
	width?: string
	height?: string
	theme?: string | object
	loading?: boolean
	notMerge?: boolean
	ref?: any
	onMouseover?: (...args: any[]) => any
	onMouseout?: (...args: any[]) => any
}

echarts.registerMap('china', china as unknown as GeoJSONCompressed)

export const EChartComponent: React.FC<Props> = (props) => {
	const {
		ref,
		theme = 'auto',
		loading = false,
		width = '100%',
		height = '100%',
		option,
		notMerge = false,
		onMouseover,
		onMouseout,
	} = props || {}

	const chartRef = useRef<HTMLDivElement>(null)
	const chartInstance = useRef<EChartsType>(null)

	const draw = useCallback(() => {
		if (chartInstance.current) {
			chartInstance.current.setOption(
				{
					...option,
					backgroundColor: 'transparent',
				},
				{
					notMerge,
				},
			)
		}
	}, [option, notMerge])

	const init = () => {
		if (!chartRef.current) return
		// 存在DOM, 则获取 EChart 实例
		chartInstance.current = echarts.getInstanceByDom(chartRef.current)!
		if (!chartInstance.current) {
			chartInstance.current = echarts.init(chartRef.current, theme)
			if (onMouseover) {
				chartInstance.current.on('mousemove', (event: object) => {
					onMouseover && onMouseover(event, chartInstance.current, option)
				})
			}
			if (onMouseout) {
				chartInstance.current.on('mouseout', (event: object) => {
					onMouseout && onMouseout(event, chartInstance.current, option)
				})
			}
			draw()
		}
	}

	useImperativeHandle(ref, () => ({
		instance: () => chartInstance.current,
		resize,
		draw,
	}))

	const resize = debounce(() => {
		chartInstance.current &&
			chartInstance.current.resize({ animation: { duration: 300 } })
	}, 300)

	useEffect(() => {
		init()
		window.addEventListener('resize', resize)
		return () => {
			chartInstance.current && chartInstance.current.dispose()
			window.removeEventListener('resize', resize)
		}
	}, [])

	useEffect(() => {
		loading
			? chartInstance.current?.showLoading()
			: chartInstance.current?.hideLoading()
	}, [loading])

	return <div ref={chartRef} style={{ width, height }} />
}
